using Microsoft.Win32;
using NEM.Networking_Classes;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace NEM
{
    /// <summary>
    /// This Static Class contains all the Global classes that will be needed in the application like settings etc.
    /// </summary>
    public static class Globals
    {
        #region Private Variables / Constants

        #endregion

        #region Properties
        /// <summary>
        /// The public Application settings
        /// </summary>
        public static ApplicationSettings ApplicationSettings = new ApplicationSettings();
        public static Log Logger = new Log();


        private static String _ApplicationFolderPath = Path.GetDirectoryName(Application.ExecutablePath);            
        [Category("Info")]
        [DisplayName("Application FolderPath")]
        [Description("Application Folder Path")]
        public static String ApplicationFolderPath
        {
            get {
                    if (!_ApplicationFolderPath.EndsWith("\\"))
                    {
                        _ApplicationFolderPath += "\\";
                    }

                    return _ApplicationFolderPath;
                }
            set { _ApplicationFolderPath = value; }
        }
        #endregion

        #region Methods

        #region Save and Load ApplicationSettings

        /// <summary>
        /// Saves the application settings.
        /// </summary>
        /// <param name="pSaveType">Type of the p save.</param>
        /// <param name="pFullFilePath">The p full file path.</param>
        /// <returns></returns>
        public static bool SaveApplicationSettings(SaveType pSaveType = SaveType.Registry)
        {
            bool lvResult = true;

            Globals.Logger.LogMessage(string.Format("*****Enter Function***** \nFunction: [{0}] \n Parameters: [{1}]", "SaveApplicationSettings", pSaveType.ToString()));

            if (pSaveType == SaveType.Registry)
            {
                #region Save to Save to Registry.

                Globals.Logger.LogMessage("Will be trying to Save Application Settings to Registry.");

                try
                {
                    RegistryKey lvRegKey = Registry.CurrentUser.CreateSubKey(@"Software\\Tainted Mentality\\Network Environment Manager");
                    Globals.Logger.LogMessage("Open/Create SubKey");
                    lvRegKey.SetValue("Application Settings", Globals.ApplicationSettings.ToJson(), RegistryValueKind.ExpandString);
                    Globals.Logger.LogMessage("Saved settings to Registry key.");
                }
                catch (Exception ex)
                {
                    Globals.Logger.LogMessage("Error. Was trying to Save to registry.", ex);
                    lvResult = false;
                }

                #endregion End Save to Registry.

                //Check if there is a Config File and rename it.
                #region Rename Old Config File
                if (File.Exists(Globals.ApplicationFolderPath + "Application Settings"))
                {
                    Globals.Logger.LogMessage("Found File Configuration for Application Settings. Will now try to rename File.");
                    try
                    {
                        File.Delete(Globals.ApplicationFolderPath + "Application Settings.bak");
                        File.Move(Globals.ApplicationFolderPath + "Application Settings", Globals.ApplicationFolderPath + "Application Settings.bak");
                    }
                    catch (Exception ex)
                    {
                        Globals.Logger.LogMessage("Failed to Rename Application Settings File. Exception.", ex);
                        MessageBox.Show("Error Removing Old Config File: "+ex.Message);
                        throw;
                    }
                }
                #endregion 
            }
            else
            {
                #region Save to File
                try
                {
                    StreamWriter lvStreamWriter = new StreamWriter(Globals.ApplicationFolderPath + "Application Settings", true);

                    lvStreamWriter.WriteLine(Globals.ApplicationSettings.ToJson());
                    lvStreamWriter.Flush();

                    lvStreamWriter.Close();

                    lvResult = true;
                }
                catch (Exception ex)
                {

                    lvResult = false;
                }

                #endregion End Save to File.
            }

            return lvResult;
        }

        /// <summary>
        /// Loads the application settings.
        /// </summary>
        /// <param name="pSaveType">Type of the p save.</param>
        /// <param name="pFullFilePath">The p full file path.</param>
        /// <returns></returns>
        public static bool LoadApplicationSettings(SaveType pSaveType = SaveType.Registry,string pFullFilePath = "")
        {
            bool lvResult = true;


            Globals.Logger.LogMessage(string.Format("*****Enter Function***** \nFunction: [{0}] \n Parameters: [{1}]", "LoadApplicationSettings", pSaveType.ToString()));

            if (pSaveType == SaveType.Registry)
            {
                #region Load from registry
                try
                {
                    Globals.Logger.LogMessage("Try to Open Registry Key Holding Proxy Info");

                    RegistryKey lvRegKey = Registry.CurrentUser.OpenSubKey(@"Software\\Tainted Mentality\\Network Environment Manager", true);

                    if (lvRegKey == null)
                    {
                        lvResult = false;
                        Globals.Logger.LogMessage("ERROR Could not find the Registry SubKey");
                    }
                    else
                    {
                        string lvKeyValue = lvRegKey.GetValue("Application Settings").ToString();
                        Globals.ApplicationSettings = lvKeyValue.FromJson<ApplicationSettings>();
                    }
                }
                catch (Exception ex)
                {
                    lvResult = false;
                    Globals.Logger.LogMessage("Error Was trying to load form registry.", ex);
                }

                #endregion End Load from registry
            }
            else
            {

                try
                {
                    Globals.Logger.LogMessage("Trying to load settings form File.");

                    if (File.Exists(Globals.ApplicationFolderPath + "Application Settings"))
                    {
                        string lvJsonString = string.Empty;

                        StreamReader lvStreamReader = new StreamReader(Globals.ApplicationFolderPath + "Application Settings");
                        lvJsonString = lvStreamReader.ReadToEnd();
                        lvStreamReader.Close();

                        Globals.ApplicationSettings = lvJsonString.FromJson<ApplicationSettings>();
                    }
                    else
                    {
                        lvResult = false;
                    }

                }
                catch (Exception ex)
                {
                    lvResult = false;
                    Globals.Logger.LogMessage("Failed to load Application Settings from file. ",ex);
                }

                //Load from File.
                lvResult = false;
            }


            Logger.FolderPath = ApplicationSettings.LogFolderPath;
            Logger.FileName = ApplicationSettings.LogFileName;


            return lvResult;
        }




        #endregion End of Save and Load ApplicationSettings

        #region Networking Methods

        /// <summary>
        /// Determines whether IP Address is Valid.
        /// </summary>
        /// <param name="pIPAddress">The p ip address.</param>
        /// <returns></returns>
        public static bool isVlaidIP(string pIPAddress)
        {
            bool lvResult = true;

            IPAddress address;
            if (IPAddress.TryParse(pIPAddress, out address))
            {
                switch (address.AddressFamily)
                {
                    case System.Net.Sockets.AddressFamily.InterNetwork:
                        //IPv4
                        break;
                    case System.Net.Sockets.AddressFamily.InterNetworkV6:
                        //IPv6
                        break;
                    default:
                        //Unknown IP Type.
                        lvResult = false;

                        break;
                }
            }

            return lvResult;
        }

        #endregion End Networking Methods


        #endregion

        #region Overrides

        #endregion

    }
}
